#pragma once
#include <iostream>
#include "Socket.hpp"
#include <memory>
#include "Connection.hpp"
#include "InetAddr.h"
#include "IOService.hpp"
#include "Epoller.hpp"
using namespace std;

class Listener
{
public:
    Listener(uint16_t port,IOService& func)
        : _port(port), _listensock(make_unique<TcpSocket>()),_io(func)
    {
        InetAddr addr("0", port);
        _listensock->BuildListenSocket(addr);
    }
    int Sockfd()
    {
        return _listensock->sockfd();
    }
    // 这里用不用_listensock是无所谓的，conn也有对应的fd,且在处理传参时那里的包装器也有用
    void Accepter(Connection *conn)
    {
        while (1)
        {
            InetAddr client;
            int code = 0;
            int sockfd = _listensock->AcceptSocket(&client, &code);
            if (sockfd >= 0)
            {
                //listen回指向Reactor容器，添加新收到的链接
                //普通IO读，写，异常操作，解耦到另一个类
                conn->_r->AddConnection(
                    sockfd,
                    EPOLLIN | EPOLLET,
                    bind(&IOService::HandlerRecv,&_io,placeholders::_1),
                    bind(&IOService::HandlerSend,&_io,placeholders::_1),
                    bind(&IOService::HandlerExcept,&_io,placeholders::_1));
            }
            else
            {
                if (code == EWOULDBLOCK || code == EAGAIN)
                {
                    LOG(INFO, "accept full,can not accept,sockfd: %d", sockfd);
                    break;
                }
                else if(code == EINTR)
                {
                    LOG(INFO,"accept interrupt by signal,sockfd: %d", sockfd);
                    continue;
                }
                else
                {
                    LOG(ERROR,"accept fail,sockfd: %d", sockfd);
                    break;
                }
            }
        }
    }

    ~Listener()
    {
        _listensock->Close();
    }

private:
    uint16_t _port;
    unique_ptr<Socket> _listensock;
    IOService& _io;
};